{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 生成器和迭代器"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 生成器， generator \n",
    "\n",
    "- 保存的是算法\n",
    "- 一遍循环一遍计算的机制，节约内存，惰性计算"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. 列表生成式\n",
    "2. 带yield的generator function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<generator object <genexpr> at 0x000001D4309EC750>\n"
     ]
    }
   ],
   "source": [
    "g=(x*x for x in range(1,11))  # 得到一个generator 对象, generator保存的是算法\n",
    "print(g) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 取g中的元素 next(g)\n",
    "list(g)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "4\n",
      "9\n",
      "16\n",
      "25\n",
      "36\n",
      "49\n",
      "64\n",
      "81\n",
      "100\n"
     ]
    }
   ],
   "source": [
    "# 取g中的元素 for ... in ..\n",
    "for i in g:\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "# yield \n",
    "\n",
    "# 斐波那契额数列，1,1,2,3,5,8,。。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 1, 2, 3, 5, 8]"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def fib(n):\n",
    "    seq=[]\n",
    "    for i in range(0,n):\n",
    "        if i ==0 or i==1:\n",
    "            seq.append(1)\n",
    "        else:\n",
    "            seq.append(seq[i-2]+seq[i-1])\n",
    "    return seq\n",
    "\n",
    "fib(6)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object fib at 0x000001D4309EC7C8>"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def fib(max):\n",
    "    n,a,b=0,0,1\n",
    "    while n< max:\n",
    "        yield b\n",
    "        a,b=b,a+b\n",
    "        n=n+1\n",
    "    return 'done'\n",
    "\n",
    "g=fib(5)\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "ename": "StopIteration",
     "evalue": "done",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m                             Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-20-709396a5599b>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mnext\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mresult\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;31mStopIteration\u001b[0m: done"
     ]
    }
   ],
   "source": [
    "next(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 函数转变为生成器\n",
    "# 斐波那契额数列，1,1,2,3,5,8.。。\n",
    "def fib(max):\n",
    "    n,a,b=0,0,1\n",
    "    while n< max:\n",
    "        yield b   # 转为了生成器\n",
    "        a,b=b,a+b\n",
    "        n=n+1\n",
    "    return 'done'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "1\n",
      "2\n",
      "3\n",
      "5\n",
      "no data done\n"
     ]
    }
   ],
   "source": [
    "#try and except\n",
    "while True:\n",
    "    try:\n",
    "        x=next(g)\n",
    "        print(x)\n",
    "    except StopIteration as e:   # 停止生成器异常\n",
    "        print('no data',e.value)\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 迭代器\n",
    "\n",
    "for循环可以应用于下列类型：\n",
    "\n",
    ">集合数据类型，list,tuple, dict, set,str等\n",
    "    \n",
    "> generator， 生成器和带yield的generator ftn 等\n",
    "\n",
    "迭代和遍历是一回事儿\n",
    "\n",
    "直接可用作于for循环的叫可迭代对象： iterable\n",
    "\n",
    "直接可作用于next方法的叫可以生成器对象：Iterator\n",
    "\n",
    "生成器可以同时作用于for 循环和next()函数，不断调用，直到抛出StopIteration错误"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 判断一个对象是否是可迭代，"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [],
   "source": [
    "from collections import Iterable  # collections 集合类\n",
    "from collections.abc import Iterator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "print(isinstance([],Iterable))\n",
    "print(isinstance('dbd',Iterable))\n",
    "print(isinstance(12,Iterable))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "False\n",
      "False\n",
      "False\n"
     ]
    }
   ],
   "source": [
    "# 判断是不是生成器对象 Iterator\n",
    "print(isinstance([],Iterator))\n",
    "print(isinstance('dbd',Iterator))\n",
    "print(isinstance(12,Iterator))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "True\n",
      "True\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "# 转换为生成器, 生成器对象表现的是一个数据流，不断被next调用，不能知道长度是多少，\n",
    "#有需要就返回下一个数据\n",
    "\n",
    "#iter([])\n",
    "\n",
    "print(isinstance(iter([]),Iterator))\n",
    "print(isinstance(iter('dbd'),Iterator))\n",
    "print(isinstance(iter({}),Iterator))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 练习：杨辉三角 (使用generator 打印杨辉三角)\n",
    "\n",
    "# 输出结果为：\n",
    "# [1]\n",
    "# [1,1]\n",
    "# [1,2,1]\n",
    "# [1,3,3,1]\n",
    "# [1,4,6,4,1]       "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<generator object yanghui at 0x000001D430A7F570>"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def yanghui(n):\n",
    "    seq=[]\n",
    "    for i in range(1,n+1):\n",
    "        if i==1:\n",
    "            temp = [1]\n",
    "            seq.append(temp)\n",
    "        else:\n",
    "            temp=[x+y for x,y in zip([0]+seq[-1],seq[-1]+[0])]\n",
    "            seq.append(temp)\n",
    "        yield temp\n",
    "    return   \n",
    "\n",
    "g=yanghui(5)\n",
    "g"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1, 2, 1]"
      ]
     },
     "execution_count": 31,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "next(g)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
